package start.util;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import org.apache.commons.lang3.reflect.TypeUtils;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

public class FastJsonUtil {

    /**
     * 将 json 字符串转换成指定类型的对象
     * @param json json 字符串
     * @param clazz 目标对象的 Class
     * @param <T> 目标对象类型
     * @return 目标对象
     */
    public static <T> T fromJson(String json, Class<T> clazz) {
        return JSON.parseObject(json, clazz);
    }

    /**
     * 将 json 字符串转换成指定类型的泛型对象
     * @param json json 字符串
     * @param clazz 目标泛型对象的 Class
     * @param <T> 目标泛型对象类型
     * @return 目标泛型对象
     */
    public static <T> T fromJson(String json, Class<T> clazz, Class<?>... parameterClasses) {
        Type type = buildParameterizedType(clazz, parameterClasses);
        return JSON.parseObject(json, type);
    }

    /**
     * 将对象转换成 json 字符串
     * @param obj 待转换对象
     * @return json 字符串
     */
    public static String toJson(Object obj) {
        return JSON.toJSONString(obj);
    }

    /**
     * 将 json 字符串转换成 List 对象
     * @param json json 字符串
     * @param clazz List 中元素的 Class
     * @param <T> List 中元素类型
     * @return List 对象
     */
    public static <T> List<T> fromJsonToList(String json, Class<T> clazz) {
        return JSON.parseArray(json, clazz);
    }

    /**
     * 将 json 字符串转换成 List 对象
     * @param json json 字符串
     * @param clazz List 中元素的 Class
     * @param <T> List 中元素类型
     * @return List 对象
     */
    public static <T> List<? extends T> fromJsonToList(String json, Class<T> clazz, Class<?>... parameterClasses) {
        Type type = TypeUtils.parameterize(clazz, parameterClasses);
        Type type1 = TypeUtils.parameterize(List.class, type);
        return JSONArray.parseObject(json, type1);
    }

    /**
     * 将 json 字符串转换成 Map 对象
     * @param json json 字符串
     * @param keyClass Map 的 key 的 Class
     * @param valueClass Map 的 value 的 Class
     * @param <K> Map 的 key 类型
     * @param <V> Map 的 value 类型
     * @return Map 对象
     */
    public static <K, V> Map<K, V> fromJsonToMap(String json, Class<K> keyClass, Class<V> valueClass) {
        return JSON.parseObject(json, buildParameterizedType(Map.class, keyClass, valueClass));
    }

    /**
     * 构建 ParameterizedType 对象
     * @param clazz 目标泛型类型的 Class
     * @param parameterClasses 泛型参数类型的 Class 数组
     * @return ParameterizedType 对象
     */
    private static ParameterizedType buildParameterizedType(Class<?> clazz, Class<?>... parameterClasses) {
        return new ParameterizedType() {
            @Override
            public Type[] getActualTypeArguments() {
                return parameterClasses;
            }

            @Override
            public Type getRawType() {
                return clazz;
            }

            @Override
            public Type getOwnerType() {
                return null;
            }
        };
    }
}